import { AppLoadingHelper, ControlVOBase } from '@/core/modules';
import {
	DECtrlActionType,
	IContext,
	ICtrlDataAction,
	ICtrlService,
	IDECtrlAbility,
	IDECtrlController,
	IDECtrlControllerParams,
	IDECtrlModel,
	IDECtrlStore,
	IHttpResponse,
	IOpenViewResult,
	IParam,
	IUIService,
} from '../../interface';
import { CtrlController } from './ctrl-controller';

/**
 * 实体部件控制器
 *
 * @export
 * @class DECtrlController
 * @extends {CtrlController<T, S, A>}
 * @implements {IDECtrlController}
 * @template T
 * @template S
 * @template A
 */
export class DECtrlController<
		T,
		S extends IDECtrlStore,
		A extends IDECtrlAbility
	>
	extends CtrlController<T | DECtrlActionType, S, A>
	implements IDECtrlController<S, A>
{
	/**
	 * 部件节点ID
	 *
	 * @protected
	 * @type {string}
	 * @memberof DECtrlController
	 */
	protected controlID!: string;

	/**
	 * 实体部件模型
	 *
	 * @protected
	 * @type {IDECtrlModel}
	 * @memberof DECtrlController
	 */
	protected declare model: IDECtrlModel;

	/**
	 * 部件服务
	 *
	 * @protected
	 * @type {*}
	 * @memberof CtrlController
	 */
	protected ctrlService!: ICtrlService<ControlVOBase>;

	/**
	 * 行为集合
	 *
	 * @protected
	 * @type {IParam}
	 * @memberof DECtrlController
	 */
	protected actions: ICtrlDataAction = {};

	/**
	 * 打开视图
	 *
	 * @protected
	 * @type {(Function | undefined)}
	 * @memberof DECtrlController
	 */
	protected openView: Function | undefined;

	/**
	 * 新建视图
	 *
	 * @protected
	 * @type {(Function | undefined)}
	 * @memberof DECtrlController
	 */
	protected newView: Function | undefined;

	/**
	 * 界面行为服务
	 *
	 * @protected
	 * @type {IUIService}
	 * @memberof DECtrlController
	 */
	protected uiService?: IUIService;

	/**
	 * Creates an instance of DECtrlController.
	 * @param {IDECtrlControllerParams<DECtrlActionType, IDECtrlAbility>} params
	 * @memberof DECtrlController
	 */
	public constructor(
		params: IDECtrlControllerParams<DECtrlActionType, IDECtrlAbility>
	) {
		super(params);
	}

	/**
	 * 处理部件初始化
	 *
	 * @protected
	 * @param {(IDECtrlControllerParams<T | DECtrlActionType, A>)} params
	 * @memberof DECtrlController
	 */
	protected processCtrlInit(
		params: IDECtrlControllerParams<T | DECtrlActionType, A>
	): void {
		super.processCtrlInit(params);
		Object.assign(this.store, {
			loadingHelper: AppLoadingHelper.getInstance(
				'CONTROL',
				params.pLoadingHelper
			),
		});
	}

	/**
	 * 部件初始化前（准备必要参数）
	 *
	 * @protected
	 * @param {IDECtrlControllerParams<DECtrlActionType, IDECtrlAbility>} params
	 * @memberof ChartController
	 */
	protected beforeCtrlInit(
		params: IDECtrlControllerParams<DECtrlActionType, IDECtrlAbility>
	) {
		super.beforeCtrlInit(params);
		this.openView = params.openView;
		this.newView = params.newView;
		if (params.actions) {
			this.actions = params.actions;
		}
		this.controlID = params.controlID;
		if (params.ctrlService) {
			this.ctrlService = params.ctrlService;
		}
		this.initUIService();
	}

	/**
	 * 初始化UI服务
	 *
	 * @private
	 * @memberof DECtrlController
	 */
	private initUIService() {
		if (this.model && this.model.entityCodeName) {
			App.getUIService(this.model.entityCodeName).then(
				(service: IUIService) => {
					this.uiService = service;
				}
			);
		}
	}

	/**
	 * 打开视图
	 *
	 * @return {*}  {void}
	 * @memberof DECtrlController
	 */
	public openData(
		context: IContext,
		viewParams: IParam,
		data: IParam[]
	): Promise<IOpenViewResult> | void {
		if (this.openView) {
			return this.openView(context, viewParams, data);
		}
	}

	/**
	 * 新建视图
	 *
	 * @return {*}  {void}
	 * @memberof DECtrlController
	 */
	public newData(
		context: IContext,
		viewParams: IParam,
		data: IParam[]
	): Promise<IOpenViewResult> | void {
		if (this.newView) {
			return this.newView(context, viewParams, data);
		}
	}

	/**
	 * 异步行为之前
	 *
	 * @param {string} action
	 * @param {IContext} context
	 * @param {IParam} params
	 * @memberof DECtrlController
	 */
	public beforeAsyncAction(action: string, context: IContext, params: IParam) {
		const { loadingHelper } = this.store;
		loadingHelper.beginLoading(this.controlID);
	}

	/**
	 * 异步行为之后
	 *
	 * @param {string} action
	 * @param {IHttpResponse} response
	 * @memberof DECtrlController
	 */
	public afterAsyncAction(action: string, response: IHttpResponse) {
		const { loadingHelper } = this.store;
		loadingHelper.endLoading();
	}

	/**
	 * 获取部件能力
	 *
	 * @return {*}  {A}
	 * @memberof MDCtrlController
	 */
	public getAbility(): A {
		return {
			...super.getAbility(),
			openData: this.openData.bind(this),
			newData: this.newData.bind(this),
			getData: this.getData.bind(this),
		};
	}
}
